package com.example.performance.engine;

import com.example.performance.executor.HttpRequestExecutor;
import com.example.performance.model.HttpRequest;
import com.example.performance.model.RequestResult;
import com.example.performance.model.TestScenario;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;

/**
 * 场景执行器
 * 负责执行单个测试场景中的所有HTTP请求
 */
public class ScenarioExecutor {

    private static final Logger logger = LoggerFactory.getLogger(ScenarioExecutor.class);

    private final HttpRequestExecutor httpExecutor;
    private final ExecutorService executorService;

    public ScenarioExecutor() {
        this.httpExecutor = new HttpRequestExecutor();
        // 创建线程池用于并行执行请求
        this.executorService = Executors.newCachedThreadPool(r -> {
            Thread thread = new Thread(r);
            thread.setName("ScenarioExecutor-" + thread.getId());
            thread.setDaemon(true);
            return thread;
        });
    }

    /**
     * 执行测试场景
     * 
     * @param scenario      测试场景
     * @param globalHeaders 全局请求头
     * @return 执行结果列表
     */
    public List<RequestResult> executeScenario(TestScenario scenario, Map<String, String> globalHeaders) {
        if (scenario == null || !scenario.isEnabled()) {
            return new ArrayList<>();
        }

        logger.info("开始执行场景: {} ({})", scenario.getName(), scenario.getDescription());
        List<RequestResult> allResults = new ArrayList<>();

        try {
            // 根据重复次数执行场景
            for (int i = 0; i < scenario.getRepeatCount(); i++) {
                logger.debug("执行场景第{}次: {}", i + 1, scenario.getName());
                List<RequestResult> results = executeScenarioOnce(scenario, globalHeaders);
                allResults.addAll(results);

                // 如果不是最后一次执行，等待间隔时间
                if (i < scenario.getRepeatCount() - 1 && scenario.getDelayBetweenRequests() > 0) {
                    Thread.sleep(scenario.getDelayBetweenRequests());
                }
            }

            logger.info("场景执行完成: {}, 总请求数: {}", scenario.getName(), allResults.size());

        } catch (InterruptedException e) {
            logger.warn("场景执行被中断: {}", scenario.getName());
            Thread.currentThread().interrupt();
        } catch (Exception e) {
            logger.error("场景执行失败: {}", scenario.getName(), e);
        }

        return allResults;
    }

    /**
     * 执行场景一次
     * 
     * @param scenario      测试场景
     * @param globalHeaders 全局请求头
     * @return 执行结果列表
     */
    private List<RequestResult> executeScenarioOnce(TestScenario scenario, Map<String, String> globalHeaders)
            throws InterruptedException, ExecutionException {

        List<HttpRequest> requests = scenario.getRequests();
        if (requests.isEmpty()) {
            return new ArrayList<>();
        }

        if (scenario.getExecutionMode() == TestScenario.ExecutionMode.PARALLEL) {
            return executeRequestsInParallel(requests, globalHeaders, scenario.getDelayBetweenRequests());
        } else {
            return executeRequestsSequentially(requests, globalHeaders, scenario.getDelayBetweenRequests());
        }
    }

    /**
     * 串行执行请求
     * 
     * @param requests      请求列表
     * @param globalHeaders 全局请求头
     * @param delay         请求间延迟
     * @return 执行结果列表
     */
    private List<RequestResult> executeRequestsSequentially(List<HttpRequest> requests,
            Map<String, String> globalHeaders,
            long delay) throws InterruptedException {
        List<RequestResult> results = new ArrayList<>();

        for (int i = 0; i < requests.size(); i++) {
            HttpRequest request = requests.get(i);
            logger.debug("执行请求 [{}/{}]: {}", i + 1, requests.size(), request.getName());

            RequestResult result = httpExecutor.execute(request, globalHeaders);
            results.add(result);

            // 如果不是最后一个请求，等待延迟时间
            if (i < requests.size() - 1 && delay > 0) {
                Thread.sleep(delay);
            }
        }

        return results;
    }

    /**
     * 并行执行请求
     * 
     * @param requests      请求列表
     * @param globalHeaders 全局请求头
     * @param delay         请求间延迟（并行模式下此参数被忽略）
     * @return 执行结果列表
     */
    private List<RequestResult> executeRequestsInParallel(List<HttpRequest> requests,
            Map<String, String> globalHeaders,
            long delay) throws InterruptedException, ExecutionException {

        logger.debug("并行执行{}个请求", requests.size());

        // 创建任务列表
        List<Future<RequestResult>> futures = new ArrayList<>();

        for (HttpRequest request : requests) {
            Future<RequestResult> future = executorService.submit(() -> {
                logger.debug("并行执行请求: {}", request.getName());
                return httpExecutor.execute(request, globalHeaders);
            });
            futures.add(future);
        }

        // 收集结果
        List<RequestResult> results = new ArrayList<>();
        for (Future<RequestResult> future : futures) {
            try {
                RequestResult result = future.get(60, TimeUnit.SECONDS); // 最大等待60秒
                results.add(result);
            } catch (TimeoutException e) {
                logger.error("并行请求执行超时", e);
                future.cancel(true); // 取消超时的任务

                // 创建一个失败的结果
                RequestResult failureResult = new RequestResult("超时请求", "unknown", "unknown");
                failureResult.markFailure("请求执行超时");
                results.add(failureResult);
            }
        }

        return results;
    }

    /**
     * 关闭执行器，释放资源
     */
    public void shutdown() {
        logger.info("关闭场景执行器");

        if (executorService != null && !executorService.isShutdown()) {
            executorService.shutdown();
            try {
                if (!executorService.awaitTermination(10, TimeUnit.SECONDS)) {
                    logger.warn("执行器未能在10秒内正常关闭，强制关闭");
                    executorService.shutdownNow();
                }
            } catch (InterruptedException e) {
                logger.warn("等待执行器关闭时被中断");
                executorService.shutdownNow();
                Thread.currentThread().interrupt();
            }
        }

        if (httpExecutor != null) {
            httpExecutor.close();
        }
    }

    /**
     * 检查执行器是否健康
     * 
     * @return 是否健康
     */
    public boolean isHealthy() {
        return httpExecutor != null && httpExecutor.isHealthy() &&
                executorService != null && !executorService.isShutdown();
    }
}